import io
import sys

def readWord( ):
    word = ""
    c = sys.stdin.read(1)
    while c.isspace() :
        c = sys.stdin.read(1)

    while not c.isspace() :
        word += c
        c = sys.stdin.read(1)

    return word

def readInt( ):
    return int(readWord())

def readNxNMatrix(n, readF):
    matrix = []
    for _ in range(n):
        line = []
        for _ in range(n):
            line.append(readF())
        matrix.append(line)
    return matrix


#Sudoku class
class Sudoku:

    def __init__(self, n, data=None):
        self.n = n
        if(data == None):
            self.data = readNxNMatrix(n, readInt)
        else:
            self.data = data

    def dup(self):
        dupData = []
        for l in self.data:
            dupData.append(list(l))

        return Sudoku(self.n, dupData)

    def getRow(self, row):
        return self.data[row]

    def getColumn(self, col):
        return map(lambda row: self.data[row][col], range(self.n))

    @staticmethod
    def allDifferent(l):
        return len(set(l)) == len(l)

    @staticmethod
    def onlyValidNumbers(l, n):
        return not (set(l) - set(range(n+1)))

    def isValid(self):
        for i in range(self.n):
            row = self.getRow(i)
            row = filter(lambda e: e != 0, row)
            if(not (Sudoku.allDifferent(row) and
                    Sudoku.onlyValidNumbers(row, self.n))):
                return False

            col = self.getColumn(i)
            col = filter(lambda e: e != 0, col)
            if(not (Sudoku.allDifferent(col) and
                    Sudoku.onlyValidNumbers(col, self.n))):
                return False

        return True

    def getEmptyCells(self):
        emptyCells = []
        for i in range(self.n):
            for j in range(self.n):
                if(self.data[i][j] == 0):
                    emptyCells.append((i,j))

        return emptyCells


    def getCandidateListForEmptyCell(self,(i,j)):
        row = filter(lambda e: e != 0, self.getRow(i))
        col = filter(lambda e: e != 0, self.getColumn(j))
        return list(set(range(1,self.n+1)) -  set(row).union(set(col)))

    def setCell(self,(i,j), e):
        self.data[i][j] = e

    def solve(self):
        emptyCells = self.getEmptyCells()

        candidateList = map(lambda cell: (cell,self.getCandidateListForEmptyCell(cell)),
                            emptyCells)

        if(len(emptyCells) == 0):
            return [self]
        else:
            (eCell,cList)  = min(candidateList, key=lambda (_,l): len(l))

            if(not cList):
                return []
            else:
                result = []
                for candidate in cList:
                    selfDup = self.dup()
                    selfDup.setCell(eCell, candidate)
                    _result = selfDup.solve()
                    result += _result

                return result

    def printSudoku(self):
        print ('=' * (self.n * 2))
        for row in self.data:
            for e in row:
                print str(e),
            print
        print ('=' * (self.n * 2))


#calling main
def main( ):

    try:
        print 'Welcome to BMK\'s Sudoku solver!'
        n = int(raw_input('What dimension has your Sudoku? '))
        sudoku = Sudoku(n)
        result = sudoku.solve()
        if(not result):
            print 'I couldn\'t solve your input. I am sorry...'
        else:
            for sdk in result:
                sdk.printSudoku()
            print 'Solved! Have a nice day!'

    except:
        print 'Something bad happened! Maybe your input was incorrect...'

#calling the main function
main()

